package com.nageoffer.shortlink.project.mq.idempotent;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

// 消息队列幂等处理器
// 使用Redis实现基于唯一消息ID的幂等控制方案
@Component
@RequiredArgsConstructor
public class MessageQueueIdempotentHandler {

    private final StringRedisTemplate stringRedisTemplate;  // Redis操作模板

    // Redis键前缀，用于隔离不同业务的幂等键
    private static final String IDEMPOTENT_KEY_PREFIX = "short-link:idempotent:";

    // 判断消息是否已被处理
    // 返回值说明：true=首次处理，false=重复消息
    public boolean isMessageProcessed(String messageId) {
        // 构造完整Redis键（业务前缀+消息ID）
        String key = IDEMPOTENT_KEY_PREFIX + messageId;
        // 原子操作：仅当key不存在时设置值（0=处理中），有效期2分钟
        return Boolean.TRUE.equals(stringRedisTemplate.opsForValue().setIfAbsent(key, "0", 2, TimeUnit.MINUTES));
    }

    // 检查消息是否已完成处理
    // 通过判断Redis中存储的状态值是否为"1"
    public boolean isAccomplish(String messageId) {
        String key = IDEMPOTENT_KEY_PREFIX + messageId;
        // 获取当前状态值（null=未处理，0=处理中，1=已完成）
        return Objects.equals(stringRedisTemplate.opsForValue().get(key), "1");
    }

    // 标记消息处理完成
    // 将状态更新为"1"并刷新有效期
    public void setAccomplish(String messageId) {
        String key = IDEMPOTENT_KEY_PREFIX + messageId;
        // 更新状态为已完成，保持2分钟有效期（防止极端情况下的状态丢失）
        stringRedisTemplate.opsForValue().set(key, "1", 2, TimeUnit.MINUTES);
    }

    // 异常时清除处理状态
    // 允许消息重新被消费（配合消息队列重试机制）
    public void delMessageProcessed(String messageId) {
        String key = IDEMPOTENT_KEY_PREFIX + messageId;
        // 删除状态记录，使消息可重新进入处理流程
        stringRedisTemplate.delete(key);
    }
}